/** 
    @file frame_listener.cpp 
    @brief Frame Listener class functions
*/
#include "frame_listener.hpp"

pm3::FRAME_LISTENER::FRAME_LISTENER() {
	m_time = 0.0;

    m_mouse_state = 0;
}

pm3::FRAME_LISTENER::~FRAME_LISTENER() {
}

bool pm3::FRAME_LISTENER::frameEnded( const Ogre::FrameEvent &r_event ) {
    pm3::INTERFACE *intf = pm3::INTERFACE::getSingletonPtr();
    float worst = 0, avg = 0, best = 0;
    std::string str;

    if (intf && intf->get_render_window()) {
        // Update FPS on the overlay
        worst = intf->get_render_window()->getWorstFPS();
        avg = intf->get_render_window()->getAverageFPS();
        best = intf->get_render_window()->getBestFPS();

        str = "FPS: " + pm3::util::to_str( worst )  + " .. " +
                        pm3::util::to_str( avg ) + " .. " +
                        pm3::util::to_str( best );
        pm3::hud::TEXT_OVERLAY::getSingleton().set_text( "FPS", str );
    }

	return true;
}

bool pm3::FRAME_LISTENER::frameStarted( const Ogre::FrameEvent &r_event ) {
    pm3::PHYSICS *physics = pm3::PHYSICS::getSingletonPtr();
    pm3::PIXELWORLD *world = pm3::PIXELWORLD::getSingletonPtr();
    int num_movement_keys = 0;
    float mouse_sensitivity = 0;
    Ogre::Vector2 mouse_delta;

    // Keyboard
    {
        // Go forward
        if (m_keymap [Qt::Key_W]) {
            world->m_player.move( Ogre::Vector3( 0.0f, 0.0f, -r_event.timeSinceLastFrame ) );
            num_movement_keys++;
        }
        // Go backwards
        if (m_keymap [Qt::Key_S]) {
            world->m_player.move( Ogre::Vector3( 0.0f, 0.0f, r_event.timeSinceLastFrame ) );
            num_movement_keys++;
        }
        // Strafe left
        if (m_keymap [Qt::Key_A]) {
            world->m_player.move( Ogre::Vector3( -r_event.timeSinceLastFrame, 0.0f, 0.0f ) );
            num_movement_keys++;
        }
        // Strafe right
        if (m_keymap [Qt::Key_D]) {
            world->m_player.move( Ogre::Vector3( r_event.timeSinceLastFrame, 0.0f, 0.0f ) );
            num_movement_keys++;
        }

        // No movement? Stop the player then
        if (num_movement_keys == 0)
            world->m_player.stop();
    }

    // Mouse
    {
        mouse_sensitivity = pm3::PIXELWORLD::getSingleton().m_player.get_mouse_sensitivity();

        mouse_delta = m_mouse_new_pos - m_mouse_old_pos;
        mouse_delta *= -r_event.timeSinceLastFrame * mouse_sensitivity;

        if (( m_mouse_state & Qt::RightButton ) != 0) {
            world->m_player.angle_rotate( Ogre::Degree( mouse_delta.x ), 
                                          Ogre::Degree( mouse_delta.y ) );
        }
    }

    // Update physics
    if (physics && physics->get_physics_world()) {
        // Update bullet world
        //! \note The third argument is fixed timestep, which should be small enough to allow for enough iterations during one frame
        physics->get_physics_world()->stepSimulation( r_event.timeSinceLastFrame, 10, 1.0f / 200.0f );
        physics->get_physics_world()->debugDrawWorld();

        physics->get_physics_debug()->step();
    }

    // Update world
    if (world)
        world->update();

    // Update the camera debug overlay text
    pm3::hud::TEXT_OVERLAY::getSingleton().set_text( "Camera", pm3::PIXELWORLD::getSingleton().m_player.get_pos_str() );

	return true;
}
